package com.zwf.checkstyledemo1.checks;

import com.puppycrawl.tools.checkstyle.api.*;
import java.util.*;

public class UnusedVariableCheck extends AbstractCheck {
    private final Map<String, DetailAST> variableDeclarations = new HashMap<>();
    private final Set<String> usedVariables = new HashSet<>();

    @Override
    public int[] getDefaultTokens() {
        return new int[] {
                TokenTypes.VARIABLE_DEF,
                TokenTypes.IDENT
        };
    }

    @Override
    public int[] getAcceptableTokens() {
        return getDefaultTokens();
    }

    @Override
    public int[] getRequiredTokens() {
        return getDefaultTokens();
    }

    @Override
    public void beginTree(DetailAST rootAST) {
        variableDeclarations.clear();
        usedVariables.clear();
    }

    @Override
    public void visitToken(DetailAST ast) {
        if (ast.getType() == TokenTypes.VARIABLE_DEF) {
            handleVariableDefinition(ast);
        } else if (ast.getType() == TokenTypes.IDENT) {
            handleVariableUsage(ast);
        }
    }

    @Override
    public void finishTree(DetailAST rootAST) {
        for (Map.Entry<String, DetailAST> entry : variableDeclarations.entrySet()) {
            String varName = entry.getKey();
            if (!usedVariables.contains(varName)) {
                DetailAST ast = entry.getValue();
                log(ast, "未使用的变量: '" + varName + "'");
            }
        }
    }

    private void handleVariableDefinition(DetailAST ast) {
        DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
        if (ident != null) {
            String varName = ident.getText();
            variableDeclarations.put(varName, ast);
        }
    }

    private void handleVariableUsage(DetailAST ast) {
        if (isVariableUsage(ast)) {
            usedVariables.add(ast.getText());
        }
    }

    private boolean isVariableUsage(DetailAST identAst) {
        DetailAST parent = identAst.getParent();
        return parent.getType() != TokenTypes.VARIABLE_DEF &&
                parent.getType() != TokenTypes.METHOD_DEF &&
                parent.getType() != TokenTypes.PARAMETER_DEF;
    }
}